@use '@material/dialog' as mdc-dialog;
@use '@material/animation/animation' as mdc-animation;
@use '@material/dialog/dialog-theme' as mdc-dialog-theme;
@use '../core/tokens/m2/mdc/dialog' as tokens-mdc-dialog;
@use '../core/tokens/m2/mat/dialog' as tokens-mat-dialog;
@use '../core/mdc-helpers/mdc-helpers';
@use '../core/tokens/token-utils';
@use '../core/style/variables';
@use './mdc-dialog-structure-overrides';

// Dialog content max height. This has been copied from the standard dialog
// and is needed to make the dialog content scrollable.
$mat-dialog-content-max-height: 65vh !default;
// Dialog button horizontal margin. This has been extracted from MDC as they
// don't expose this value as variable.
$mat-dialog-button-horizontal-margin: 8px !default;

// Whether to emit fallback values for the structural styles. Previously MDC was emitting
// paddings in the static styles which meant that users would get them even if they didn't
// include the `dialog-base`. Eventually we should clean up the usages of this flag.
$_emit-fallbacks: true;

// Note that we disable fallback declarations, but we don't disable fallback
// values, because there are a lot of internal apps that don't include a proper
// theme in their tests.
@include mdc-helpers.disable-mdc-fallback-declarations {
  @include mdc-dialog.static-styles($query: mdc-helpers.$mdc-base-styles-query);
  @include mdc-dialog-structure-overrides.private-dialog-structure-overrides(
    $mat-dialog-content-max-height);

  .mat-mdc-dialog-container {
    // Apply the theming slots to the container using an initial set of
    // values that will be overridden in the theme styles.
    @include mdc-dialog-theme.theme-styles(tokens-mdc-dialog.get-token-slots());

    // MDC's `theme-styles` generates a variable called `--mdc-dialog-container-elevation-shadow`
    // (note the `--shadow`) while it uses `--mdc-dialog-container-elevation` to assign the
    // `box-shadow`. Remap it so the token value is picked up.
    --mdc-dialog-container-elevation: var(--mdc-dialog-container-elevation-shadow);

    // The dialog container is focusable. We remove the default outline shown in browsers.
    outline: 0;

    .mdc-dialog__container {
      transition: opacity linear var(--mat-dialog-transition-duration, 0ms);
    }

    .mdc-dialog__surface {
      transition: mdc-animation.enter(transform, var(--mat-dialog-transition-duration, 0ms));
    }

    // Angular Material supports disabling all animations when NoopAnimationsModule is imported.
    // TODO(devversion): Look into using MDC's Sass queries to separate the animation styles and
    // conditionally add them. Consider the size cost and churn when deciding whether to switch.
    &._mat-animation-noopable {
      .mdc-dialog__container, .mdc-dialog__surface {
        transition: none;
      }
    }
  }
}

@mixin _use-mat-tokens {
  @include mdc-helpers.disable-mdc-fallback-declarations {
    @include token-utils.use-tokens(tokens-mat-dialog.$prefix,
      tokens-mat-dialog.get-token-slots()) {
      @content;
    }
  }
}

// This needs extra specificity so it doesn't get overwritten by the CDK structural styles.
.cdk-overlay-pane.mat-mdc-dialog-panel {
  @include _use-mat-tokens {
    @include token-utils.create-token-slot(max-width, container-max-width, $_emit-fallbacks);
    @include token-utils.create-token-slot(min-width, container-min-width, $_emit-fallbacks);

    @media (variables.$xsmall) {
      @include token-utils.create-token-slot(max-width, container-small-max-width,
        $_emit-fallbacks);
    }
  }
}

.mat-mdc-dialog-title {
  @include _use-mat-tokens {
    @include token-utils.create-token-slot(padding, headline-padding, $_emit-fallbacks);
  }
}

// MDC sets the display behavior for title and actions, but not for content. Since we support
// using the `mdc-dialog__content` as custom element, we need to set the element to `block`.
.mat-mdc-dialog-content {
  display: block;

  @include _use-mat-tokens {
    // These styles need a bit more specificity.
    .mat-mdc-dialog-container & {
      @include token-utils.create-token-slot(padding, content-padding, $_emit-fallbacks);
    }

    // Note: we can achieve this with a `:has` selector, but it results in an
    // increased specificity which breaks a lot of internal clients.
    .mat-mdc-dialog-container-with-actions & {
      @include token-utils.create-token-slot(padding, with-actions-content-padding,
        $_emit-fallbacks);
    }
  }

  .mat-mdc-dialog-container .mat-mdc-dialog-title + & {
    padding-top: 0;
  }
}

.mat-mdc-dialog-actions {
  // For backwards compatibility, actions align at start by default. MDC usually
  // aligns actions at the end of the container.
  @include _use-mat-tokens {
    @include token-utils.create-token-slot(padding, actions-padding, $_emit-fallbacks);
    @include token-utils.create-token-slot(justify-content, actions-alignment, $_emit-fallbacks);
  }

  // .mat-mdc-dialog-actions-align-{start|center|end} are set by directive input "align"
  // [align='start'], [align='center'] and [align='right'] are kept for backwards compability
  &.mat-mdc-dialog-actions-align-start, &[align='start'] {
    justify-content: start;
  }

  &.mat-mdc-dialog-actions-align-center, &[align='center'] {
    justify-content: center;
  }

  &.mat-mdc-dialog-actions-align-end, &[align='end'] {
    justify-content: flex-end;
  }

  // MDC applies horizontal margin to buttons that have an explicit `mdc-dialog__button`
  // class applied. We can't set this class for projected buttons that consumers of the
  // dialog create. To workaround this, we select all Material Design buttons we know and
  // add the necessary spacing similar to how MDC applies spacing.
  .mat-button-base + .mat-button-base,
  .mat-mdc-button-base + .mat-mdc-button-base {
    margin-left: $mat-dialog-button-horizontal-margin;

    [dir='rtl'] & {
      margin-left: 0;
      margin-right: $mat-dialog-button-horizontal-margin;
    }
  }
}
